/**
 * 
 */
package ar.edu.utn.frsf.cidisi.ginet.generation.elementsestructure;

import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.pnml.tools.epnk.pnmlcoremodel.PlaceNode;
import org.pnml.tools.epnk.pntypes.hlpng.pntd.hlpngdefinition.Declaration;

import ar.edu.utn.frsf.cidisi.ginet.GINet;
import ar.edu.utn.frsf.cidisi.ginet.abstractginet.AbstractginetFactory;
import ar.edu.utn.frsf.cidisi.ginet.abstractginet.Page;
import ar.edu.utn.frsf.cidisi.ginet.formalization.FormalAssociation;
import ar.edu.utn.frsf.cidisi.ginet.formalization.FormalCBPLanguage;
import ar.edu.utn.frsf.cidisi.ginet.generation.elementsestructure.elementstemplate.ChoreographyStructure;
import ar.edu.utn.frsf.cidisi.ginet.generation.elementsestructure.elementstemplate.InteractionProtocolStructure;
import ar.edu.utn.frsf.cidisi.ginet.generation.managers.EMFModelLoad;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.And;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.Cancel;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.Exception;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.If;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.InteractionProtocol;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.InteractionProtocolElement;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.Loop;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.Or;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.Termination;
import ar.edu.utn.frsf.cidisi.upcolbpip.interactionprotocols.Xor;

/**
 * @author Neri
 *
 */
public class UpColbpipStructureToAbstractPage{
	
	private EList<TreeInterface> treeList;
	
	private Page pageStructure;
	
	private GINet ginet;
	
	private FormalCBPLanguage language;
	
	public UpColbpipStructureToAbstractPage(GINet ginet, InteractionProtocol rootElement){
		super();
		
		this.treeList = new BasicEList<TreeInterface>();
		EList<InteractionProtocolElement> elements = rootElement.getIpElement();		

		for (InteractionProtocolElement interactionProtocolElement : elements) {

			TreeInterface tree = new TreeImpl(interactionProtocolElement);

			this.treeList.add(tree);
		}
	
		this.pageStructure = AbstractginetFactory.eINSTANCE.createPage();
		this.ginet = ginet;
		this.language = new EMFModelLoad().load();
		this.initializeStructure();
	}

	private void initializeStructure() {

		InteractionProtocolStructure interactionProtocolStructure = new InteractionProtocolStructure(this.treeList, this.ginet.getDeclaration()) {

			@Override
			public Page getPageForElement(NodeStructure element,
					TreeInterface tree, int count, PlaceNode placeIn,
					PlaceNode placeOut, EList<Declaration> ginetDeclarations, ar.edu.utn.frsf.cidisi.ginet.abstractginet.Place termination ) {
				return createAbstractPage(element, tree, count, placeIn, placeOut, ginetDeclarations, termination);
			}
		};

		Page page = interactionProtocolStructure.createInteractionProtocol(1);
		
		this.ginet.getDeclaration().addAll(interactionProtocolStructure.getGinetDeclarations());
		
		this.pageStructure = page;
	}

	private Page createAbstractPage(NodeStructure node, TreeInterface tree, int pageCount, PlaceNode placeIn, PlaceNode placeOut, EList<Declaration> ginetDeclarations, ar.edu.utn.frsf.cidisi.ginet.abstractginet.Place termination) {
	
		String elementname = this.getInteractionProtocolElementName(node.getNode());
		
		ChoreographyStructure choreagrapy = this.getTemplateByElement(elementname, pageCount);
		choreagrapy.createPageStructure(node, tree, placeIn, placeOut, ginetDeclarations, termination);
		
		return choreagrapy.getPage();
	}
	
	/**
	 * @param name
	 * @return
	 *
	 * @author Neri
	 */
	private ChoreographyStructure getTemplateByElement(String name, int count) {
		
		EList<FormalAssociation> formalAssociations = this.language.getFormalizedElements();
		
		for (FormalAssociation formalAssociation : formalAssociations) {
			if(formalAssociation.getMetamodelElement().getElement().get(0).getName().toUpperCase().equals(name)){
				String className = formalAssociation.getFormalElement().getElement().getId();
				Class<?> classTemplate = null;
				try {
					classTemplate = Class.forName("ar.edu.utn.frsf.cidisi.ginet.generation.elementsestructure.elementstemplate." + className);
					return (ChoreographyStructure)classTemplate.getConstructor(Integer.class).newInstance(new Integer(count));
				} catch (java.lang.Exception e) {
					return null;
				}
			}
		}
		return null;
	}

	private String getInteractionProtocolElementName(
			InteractionProtocolElement ipe) {

		if (ipe instanceof And) {
			return "AND";
		}
		if (ipe instanceof Or) {
			return "OR";
		}
		if (ipe instanceof Xor) {
			return "XOR";
		}
		if (ipe instanceof If) {
			return "IF";
		}
		if (ipe instanceof Loop) {
			return "LOOP";
		}
		if (ipe instanceof Exception) {
			return "EXCEPTION";
		}
		if (ipe instanceof Cancel) {
			return "CANCEL";
		}
		if (ipe instanceof Termination) {
			return "Termination";
		}

		return null;
	}

	public Page getAbstractPage(){
		return this.pageStructure;
	}
}
